package cn.ulc.socket.weapp.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.ulc.common.constant.PubDataConstant;
import cn.ulc.common.constant.enums.AvailableStatus;
import cn.ulc.common.exception.PlatformException;
import cn.ulc.common.util.CalendarUtil;
import cn.ulc.socket.weapp.common.BaseService;
import cn.ulc.socket.common.helper.MiniAppPayHelper;
import cn.ulc.socket.weapp.model.dto.*;
import cn.ulc.socket.weapp.model.param.BindPhoneParam;
import cn.ulc.socket.weapp.model.param.MemberSaveParam;
import cn.ulc.socket.weapp.model.param.OrderParam;
import cn.ulc.socket.weapp.model.param.UserCouponParam;
import cn.ulc.socket.weapp.service.MemberServ;
import cn.ulc.store.dao.CouponDao;
import cn.ulc.store.dao.PubDataDao;
import cn.ulc.store.dao.SetInfoDao;
import cn.ulc.store.dao.goods.GoodsDao;
import cn.ulc.store.dao.goods.GoodsTypeDao;
import cn.ulc.store.dao.user.MemberDao;
import cn.ulc.store.dao.user.MemberRechargeDao;
import cn.ulc.store.dao.user.UserCouponDao;
import cn.ulc.store.dao.user.WeixinUserDao;
import cn.ulc.store.entity.Company;
import cn.ulc.store.entity.PubData;
import cn.ulc.store.entity.SetInfo;
import cn.ulc.store.entity.goods.Goods;
import cn.ulc.store.entity.goods.GoodsType;
import cn.ulc.store.entity.user.Member;
import cn.ulc.store.entity.user.MemberRecharge;
import cn.ulc.store.entity.user.UserCoupon;
import cn.ulc.store.entity.user.WeixinUser;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class MemberServImpl extends BaseService implements MemberServ {
    private static final Log log = LogFactory.get();
    MemberDao memberDao;
    MemberRechargeDao rechargeDao;
    SetInfoDao setInfoDao;
    PubDataDao pubDataDao;
    CouponDao couponDao;
    UserCouponDao userCouponDao;
    GoodsDao goodsDao;
    GoodsTypeDao goodsTypeDao;
    WxPayService wxPayService;
    WeixinUserDao weixinUserDao;

    @Override
    public UserCouponListDTO findUserCouponList(String status) {
        WeixinUser loginUser = getCurrentUser();
        List<UserCoupon> couponList = userCouponDao.findListByUserId(loginUser.getId(),status,false);
        return new UserCouponListDTO(couponList);
    }

    @Override
    public UserCouponDTO findUserCouponDetail(Long id) {
        UserCouponDTO dto = new UserCouponDTO();
        UserCoupon userCoupon = userCouponDao.findOne(id);
        if(userCoupon.getUserScope().equals(PubDataConstant.COUPON_SCOPE_GOODS)){
            Goods goods = goodsDao.findOne(userCoupon.getGoodsId());
            dto.setGoods(goods);
        }else if(userCoupon.getUserScope().equals(PubDataConstant.COUPON_SCOPE_TYPE)){
            GoodsType goodsType = goodsTypeDao.findOne(userCoupon.getGoodsTypeId());
            dto.setGoodsType(goodsType);
        }
        dto.setCoupon(userCoupon);
        return dto;
    }

    @Override
    @Transactional
    public OrderResultDTO save(MemberSaveParam param) {
        WeixinUser loginUser = getCurrentUser();
        Company loginCompany = getCurrentCompany();
        SetInfo setInfo = setInfoDao.findByCondition(loginCompany.getId());
        if(setInfo==null) throw new PlatformException("缴费失败!");
        if(!param.getPhone().equals(loginUser.getPhone())){
            WeixinUser check = weixinUserDao.findByPhone(loginCompany.getId(),param.getPhone());
            if(check!=null) throw new PlatformException("该手机号已被注册!");
        }
        loginUser.setRealName(param.getName());
        loginUser.setPhone(param.getPhone());
        loginUser.setBirthDay(param.getBirthday());
        weixinUserDao.save(loginUser);
        //创建订单
        MemberRecharge recharge = new MemberRecharge();
        setBaseInfo(recharge);
        recharge.setCompanyId(loginCompany.getId());
        recharge.setOrderNo(generateCode(loginCompany.getId()));
        recharge.setPayAmount(setInfo.getMemberAmount());
        recharge.setStatus(PubDataConstant.ORDER_UNPAID);
        recharge.setWxUserId(loginUser.getId());
        rechargeDao.save(recharge);
        return new OrderResultDTO(recharge.getOrderNo());
    }

    @Override
    public OrderResultDTO saveMemberRecharge() {
        WeixinUser loginUser = getCurrentUser();
        Company company = getCurrentCompany();
        Member member =  memberDao.findByWxUserId(loginUser.getId());
        SetInfo setInfo = setInfoDao.findByCondition(company.getId());
        if(setInfo==null) throw new PlatformException("缴费失败!");
        //创建订单
        MemberRecharge recharge = new MemberRecharge();
        setBaseInfo(recharge);
        recharge.setCompanyId(company.getId());
        recharge.setOrderNo(generateCode(company.getId()));
        recharge.setPayAmount(setInfo.getMemberAmount());
        recharge.setStatus(PubDataConstant.ORDER_UNPAID);
        recharge.setWxUserId(loginUser.getId());
        if(member!=null) recharge.setMemberId(member.getId());
        rechargeDao.save(recharge);
        return new OrderResultDTO(recharge.getOrderNo());
    }

    //生成唯一订单号
    public String generateCode(Long companyId) {
        Calendar cal = Calendar.getInstance();
        String month = (cal.get(Calendar.MONTH)+1)> 10 ? (cal.get(Calendar.MONTH)+1)+"" : "0" +(cal.get(Calendar.MONTH)+1);
        String date = cal.get(Calendar.DATE)> 10 ? cal.get(Calendar.DATE)+"" : "0" +cal.get(Calendar.DATE);
        String idStr = companyId.toString();
        if(idStr.length()<6){
            Integer len = 6-idStr.length();
            for(Integer i = 0;i<len;i++){
                idStr = "0"+idStr;
            }
        }
        String code = "M"+idStr+cal.get(Calendar.YEAR)+month+date;
        String maxOrderNo = rechargeDao.findMaxOrderNo(code);
        String orderNo = "0001";
        if (maxOrderNo != null) {
            orderNo = Integer.valueOf(maxOrderNo.substring(15))+1+"";
            Integer zeroLen = 4-orderNo.length();
            for(Integer i = 0;i<zeroLen;i++){
                orderNo = "0"+orderNo;
            }
        }
        return code+orderNo;
    }

    @Override
    public OrderPayDTO orderToPay(String ipAddress, OrderParam param) {
        String orderNo = param.getOrderNo();
        if (StrUtil.isBlank(orderNo)) throw new PlatformException("订单信息不能为空 ~");
        MemberRecharge recharge = rechargeDao.findByOrderNo(orderNo);
        if (recharge == null) throw new PlatformException("订单信息获取失败，无法支付 ~");
        if (!recharge.getStatus().equals("UNPAID")) throw new PlatformException("订单状态需为  未支付状态 ~");
        WeixinUser weixinUser = getCurrentUser();
        log.info("WeixinUser :" + weixinUser);
        if (StrUtil.isBlank(weixinUser.getOpenId())) throw new PlatformException("用户openId为空，支付失败 ~");
        WxPayUnifiedOrderRequest prepayInfo = MiniAppPayHelper.prepayInfo(orderNo,recharge.getPayAmount(), ipAddress, weixinUser.getOpenId());
//        WxPayService wxPayService = WxMiniAppHelper.getWxPayService();
        WxPayMpOrderResult payInfo = null;
        try {
            payInfo = wxPayService.createOrder(prepayInfo);
            String prepayId = payInfo.getPackageValue();
            prepayId = StringUtils.isNotBlank(prepayId) ? prepayId.substring(10) : "";
            log.info("prepayId ==== :%s", prepayId);
            recharge.setPrepayId(prepayId);
            rechargeDao.save(recharge);
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        log.info("payInfo : %s", new Gson().toJson(payInfo));
        return new OrderPayDTO(payInfo);
    }

    @Override
    public UserCouponListDTO findUserCoupon(UserCouponParam param) {
        List<UserCoupon> resultList = new ArrayList<>();
        WeixinUser loginUser = getCurrentUser();
        List<Map<String,Object>> goodsList = param.getGoodsList();
        List<UserCoupon> couponList = userCouponDao.findAvailableListByUserId(loginUser.getId(),PubDataConstant.COUPON_STATUS_USING,false,param.getGoodsAmount());
        if(couponList.size()<=0) return new UserCouponListDTO(resultList);
        Map<String,List<UserCoupon>> mapCoupon =  couponList.stream().collect(Collectors.groupingBy(UserCoupon::getUserScope));
        resultList = mapCoupon.get("ALL");
        if(resultList==null) resultList = new ArrayList<>();
        List<UserCoupon> userGoodsList = mapCoupon.get("GOODS");
        List<UserCoupon> userTypeList = mapCoupon.get("TYPE");
        if(userGoodsList !=null && userGoodsList.size()>0){
            for(UserCoupon coupon:userGoodsList){
                Long goodsId = coupon.getGoodsId();
                for(Map<String,Object> map:goodsList){
                    if(map.get("goodsId")!=null && map.get("goodsId").toString().equals(goodsId.toString()) &&  !resultList.contains(coupon)){
                        resultList.add(coupon);
                    }
                }
            }
        }
        if(userTypeList!=null && userTypeList.size()>0){
            for(UserCoupon coupon:userTypeList){
                Long goodsTypeId = coupon.getGoodsTypeId();
                for(Map<String,Object> map:goodsList){
                    if(map.get("goodsTypeId").toString().equals(goodsTypeId.toString()) && !resultList.contains(coupon)){
                        resultList.add(coupon);
                    }
                }
            }
        }

        if(resultList!=null && resultList.size()>0){
            Comparator<UserCoupon> comparator = (h1, h2) -> h1.getAmount().compareTo(h2.getAmount());
            resultList.sort(comparator.reversed());
        }
        return new UserCouponListDTO(resultList);
    }

    @Override
    @Transactional
    public Boolean bindPhone(BindPhoneParam param) {
        WeixinUser loginUser = getCurrentUser();
        Company company = getCurrentCompany();
        Member member  = memberDao.findByWxUserId(param.getId(),AvailableStatus.AVAILABLE);
        if(!param.getPhone().equals(loginUser.getPhone())){
            WeixinUser checkPhone = weixinUserDao.findByPhone(company.getId(),param.getPhone());
            if(checkPhone!=null) throw new PlatformException("该手机号已被使用!");
        }
        loginUser.setPhone(param.getPhone());
        weixinUserDao.save(loginUser);
        if(member!=null) {
            member.setPhone(param.getPhone());
            memberDao.save(member);
        }
        return true;
    }

    @Override
    public MemberPowerDTO findMemberPower() {
        String remark = "";
        PubData memberPower = pubDataDao.findByTypeAndName(PubDataConstant.DATA_TYPE_MEMBER_POWER,"会员权益");
        if(memberPower!=null) remark = memberPower.getRemark();
        return new MemberPowerDTO(remark);
    }

    @Override
    public MemberDTO findDetail() {
        WeixinUser loginUser = getCurrentUser();
        Member member = memberDao.findByWxUserId(loginUser.getId());
        return new MemberDTO(member);
    }

    @Override
    public void executeJob() {
        Company company = getCurrentCompany();
        List<Member> memberList = memberDao.findListByStatus(AvailableStatus.AVAILABLE);
        if(memberList!=null && memberList.size()>0){
            Date date = CalendarUtil.beginDate(CalendarUtil.afterDays(new Date(),-1));
            List<Member> members = new ArrayList<>();
            for(Member member:memberList){
                Date endTime = CalendarUtil.beginDate(member.getEndTime());
                if(endTime.compareTo(date) < 0){   //已过期
                    member.setStatus(AvailableStatus.FREEZE);
                    setBaseInfo(member);
                    members.add(member);
                }
            }
            memberDao.saveAll(members);
        }
    }
}
